/*
 * s_auto_plant.c
 *
 *  Created on: Sep 4, 2020
 *      Author: hemingway
 */
#include "s_auto_plant.h"

#include "s_auto_plant_para.h"
#include "s_auto_plant_msg.h"
#include "s_sd3077.h"
#include "h_cc2640r2f_adc.h"
#include <stdio.h>
#include <string.h>

#include "h_cc2640r2f_gpio.h"

#include <icall_ble_api.h>

#include "h_cc2640r2f_simpletime.h"
#include "h_cc2640r2f_pwm_simple.h"

#include "simple_peripheral_oad_offchip.h"

#include <ti/sysbios/knl/Task.h>
#include "h_cc2640r2f_rtc_innner.h"

#include "s_lock_buzzer.h"

#define S_AUTO_PLANT_POWER_CHANGE_WAIT_TIME                 500 //ms

#define S_AUTO_PLANT_GET_READY_TIME                         10 //s

typedef struct
{
  // unsigned int next_intr_day_time_sec;
  unsigned int water_check_times_flag[2];
}S_Auto_Plant_Data;

static unsigned int s_auto_plant_next_check_time_secs = 0U;
static unsigned int s_auto_plant_last_day_now_time_secs = 0U;

static S_Auto_Plant_Data s_auto_plant_datas;

signed char S_Auto_Plant_Init(void)
{
	return 0;
}


void S_Auto_Plant_Enable_Peripheral_Power(void)
{
  H_CC2640R2F_GPIO_OutputSet(AUTO_PLANT_PERIPHERAL_ENABLE_IO, 1);
  H_CC2640R2F_SimpleTime_Around_Delay(S_AUTO_PLANT_POWER_CHANGE_WAIT_TIME);
}

void S_Auto_Plant_Disable_Peripheral_Power(void)
{
  if(!BLE_Master_Connect_State)
  {
    H_CC2640R2F_GPIO_OutputSet(AUTO_PLANT_PERIPHERAL_ENABLE_IO, 0);
    H_CC2640R2F_SimpleTime_Around_Delay(S_AUTO_PLANT_POWER_CHANGE_WAIT_TIME);
  }
}

static unsigned int s_auto_plant_find_next_intr_day_time(unsigned int this_time)
{
  
  unsigned char i_loop = 0U;

  // choice the less one in them
  for(i_loop = 0U; i_loop < 3; i_loop++)
  {
    if(S_Auto_Plant_Para_Get_Water_Day_Time_Enable(&s_auto_plant_para, i_loop))
    {
      return S_Auto_Plant_Para_Get_Water_Day_Time_Value(&s_auto_plant_para, i_loop);
    }
  }

  // All time is disable
  return 0xFFFFFFFF;

}



#define S_AUTO_PLANT_MAX_TIME_TRY_TIMES               3

signed char S_Auto_Plant_Set_Start_Plan(void)
{
  unsigned char try = 0;
  signed char rslt = 0U;
  // First find next rtc interrupt time
  unsigned int day_time_sec_now = 0;

  for(try = 0; try < S_AUTO_PLANT_MAX_TIME_TRY_TIMES; try++)
  {
    day_time_sec_now = S_SD3077_Get_Time_Now_Second();
    if(day_time_sec_now >= SD3077_IMPOSSIBLE_TIME)
    {
      printf("time read faild, try it again\r\n");
      //Try it again
      Task_sleep(10000);
    }
    else
    {
      // printf("time read success, day time now is: %d\r\n", day_time_sec_now);
      s_auto_plant_last_day_now_time_secs = day_time_sec_now;
      break;
    }
  }
  
  unsigned int next_intr_day_time_sec = s_auto_plant_find_next_intr_day_time(day_time_sec_now);

  // printf("sec now is %d\r\n", day_time_sec_now);
  if(next_intr_day_time_sec + S_AUTO_PLANT_GET_READY_TIME > day_time_sec_now && next_intr_day_time_sec < day_time_sec_now)
  {
    next_intr_day_time_sec = day_time_sec_now + S_AUTO_PLANT_GET_READY_TIME;
  }

  if(0xFFFFFFFF == next_intr_day_time_sec)
  {
    // just sleep for whole day
    return (-1);
  }

  // s_auto_plant_datas.next_intr_day_time_sec = s_auto_plant_find_next_intr_day_time(next_intr_day_time_sec);

  // printf("%d, %d\r\n", next_intr_day_time_sec, s_auto_plant_datas.next_intr_day_time_sec);

  s_auto_plant_datas.water_check_times_flag[0] = 0U;
  s_auto_plant_datas.water_check_times_flag[1] = 0U;

  for(try = 0; try < S_AUTO_PLANT_MAX_TIME_TRY_TIMES; try++)
  {
#if USE_INNER_RTC
      s_auto_plant_next_check_time_secs = next_intr_day_time_sec;
//    next_intr_day_time_sec - S_SD3077_Get_Time_Now_Second();
      // printf("The next sec is %d, %d\r\n", next_intr_day_time_sec, day_time_sec_now);
      if(day_time_sec_now > next_intr_day_time_sec) {
          // set tomorrow
          
          printf("Set tomorrow at %d\r\n", s_auto_plant_next_check_time_secs);
          h_cc2640r2f_rtc_inner_ch1_setValueSec(s_auto_plant_next_check_time_secs);
      } else {
          // Set today
          // s_auto_plant_next_check_time_secs = ;
          printf("Set today about %d secs later\r\n", next_intr_day_time_sec - day_time_sec_now);
          h_cc2640r2f_rtc_inner_ch1_setValueSec(next_intr_day_time_sec - day_time_sec_now);
      }
#else
    rslt = S_SD3077_Clear_IntrFlag();

    rslt += S_SD3077_SetInt_Hour_Min_Second_ByDaySeconds(next_intr_day_time_sec);
    rslt += S_SD3077_Set_ClockAlarmMode(sd3077_clock_alarm_only_enable_seconde_min_hour);
#endif

    if(rslt)
    {
      Task_sleep(10000);
    }
    else
    {
      break;
    }
  }
  // S_SD3077_Clear_IntrFlag();
  // S_SD3077_SetInt_Hour_Min_Second_ByDaySeconds(next_intr_day_time_sec);
  // S_SD3077_Set_ClockAlarmMode(sd3077_clock_alarm_only_enable_seconde_min_hour);

  // S_SD3077_Reset_RTC_Intr(5);

  return 0;
}

signed char S_Auto_Plant_Handle_UTC_Intr(void)
{
    unsigned char try = 0;
    unsigned int day_time_sec_now = 0;

    printf("S_Auto_Plant_Handle_UTC_Intr\r\n");

#if !USE_INNER_RTC
  for(try = 0; try < S_AUTO_PLANT_MAX_TIME_TRY_TIMES; try++)
  {
    if(S_SD3077_Clear_IntrFlag())
    {
      Task_sleep(10000);
    }
    else
    {
      break;
    }
  }
#endif
  // Check the time
  for(try = 0; try < S_AUTO_PLANT_MAX_TIME_TRY_TIMES; try++)
  {
      day_time_sec_now = S_SD3077_Get_Time_Now_Second();
      if(day_time_sec_now >= SD3077_IMPOSSIBLE_TIME)
      {
        printf("time read faild, try it again\r\n");
        //Try it again
        Task_sleep(10000);
      }
      else
      {
        // printf("time read success, day time now is: %d\r\n", day_time_sec_now);
        break;
      }
  }
  printf("now is %d, last now is %d, next is %d\r\n", day_time_sec_now, s_auto_plant_last_day_now_time_secs, s_auto_plant_next_check_time_secs);
  if(day_time_sec_now  + S_AUTO_PLANT_GET_READY_TIME < s_auto_plant_next_check_time_secs || \
    (s_auto_plant_last_day_now_time_secs > s_auto_plant_next_check_time_secs && day_time_sec_now > s_auto_plant_next_check_time_secs)) {
      // Check it next time
      S_Auto_Plant_Set_Start_Plan();
      return (-5);
  }

	// S_SD3077_Clear_IntrFlag();

  S_Auto_Plant_Enable_Peripheral_Power();

  if(s_auto_plant_para_running_with_adc_value == S_Auto_Plant_Para_Get_Running_Mode(&s_auto_plant_para)) {
    // It is the next plan
    if(0U == s_auto_plant_datas.water_check_times_flag[0] && \
      0U == s_auto_plant_datas.water_check_times_flag[1])
    {
      s_auto_plant_datas.water_check_times_flag[0] = S_Auto_Plant_Para_Get_MAX_CheckTimes(&s_auto_plant_para);
      s_auto_plant_datas.water_check_times_flag[1] = s_auto_plant_datas.water_check_times_flag[0];
      // Check plants one by one
      // First check plant 0
      S_AutoPlant_Ask_Start_WaterPlant(0);
    }
    else // It is next check
    {
      if(s_auto_plant_datas.water_check_times_flag[1] > s_auto_plant_datas.water_check_times_flag[0])
      {
        S_AutoPlant_Ask_Start_WaterPlant(1);
      }
      else
      {
        S_AutoPlant_Ask_Start_WaterPlant(0);
      }
    }
  } else {
    S_AutoPlant_Ask_Start_WaterPlant(0);
  }
  

  

	return 0;
}

static signed char s_auto_plant_handle_adc_mode(unsigned char plant_num)
{
  unsigned int adc = H_CC2640R2F_ADC_Read_MicroVolts_byNum(plant_num + 1);

  printf("the adc read is %d, the need is %d\r\n", adc, S_Auto_Plant_Para_Get_ADC_Value(&s_auto_plant_para, plant_num));

  //Water first
  if(s_auto_plant_datas.water_check_times_flag[plant_num] == S_Auto_Plant_Para_Get_MAX_CheckTimes(&s_auto_plant_para))
  {
    printf("water first motor %d\r\n", plant_num);
    H_CC2640R2F_PWM_SetDuty_ByIndex(plant_num + 1, S_Auto_Plant_Para_Get_Motor_Value(&s_auto_plant_para, plant_num));
    H_CC2640R2F_PWM_StartChannel_ByIndex(plant_num + 1);
  }
  else // Not first water
  {
    // Check adc value and is not enoungh
    if(adc > S_Auto_Plant_Para_Get_ADC_Value(&s_auto_plant_para, plant_num))
    {
      
      printf("start motor %d\r\n", plant_num);
      H_CC2640R2F_PWM_SetDuty_ByIndex(plant_num + 1, S_Auto_Plant_Para_Get_Motor_Value(&s_auto_plant_para, plant_num));
      H_CC2640R2F_PWM_StartChannel_ByIndex(plant_num + 1);
      if(0 == plant_num)
      {
        // Start end clock
        S_LoopClock_Registe(loopclock_s_loopclock_handle_plant_0_a_evt, \
                            S_Auto_Plant_Para_Get_Single_Water_Time_Uint_Seconds(&s_auto_plant_para, plant_num) * 10);
      }
      else if(1 == plant_num)
      {
        // Start end clock
        S_LoopClock_Registe(loopclock_s_loopclock_handle_plant_1_b_evt, \
                            S_Auto_Plant_Para_Get_Single_Water_Time_Uint_Seconds(&s_auto_plant_para, plant_num) * 10);
      }
      
    }
    else // adc value is finished
    {
      s_auto_plant_datas.water_check_times_flag[plant_num] = 0U;
      S_Auto_Plant_Handle_Water_Plant_Next(plant_num);
    }
  }

  return 0;
}

static signed char s_auto_plant_handle_specail_water_time(unsigned char plant_num)
{
  unsigned int water_time = S_Auto_Plant_Para_Get_Single_Water_Time_Uint_Seconds(&s_auto_plant_para, plant_num);
  printf("start motor %d\r\n", plant_num);
  H_CC2640R2F_PWM_SetDuty_ByIndex(plant_num + 1, S_Auto_Plant_Para_Get_Motor_Value(&s_auto_plant_para, plant_num));
  H_CC2640R2F_PWM_StartChannel_ByIndex(plant_num + 1);

  printf("the single water time is %d--plant num %d\r\n", water_time, plant_num);
  S_Lock_Buzzer_Success();

  if(0 == plant_num)
  {
    // Start end clock
    S_LoopClock_Registe(loopclock_s_loopclock_handle_plant_0_a_evt, \
                      water_time * 10);
  }
  else if(1 == plant_num)
  {
    // Start end clock
    S_LoopClock_Registe(loopclock_s_loopclock_handle_plant_1_b_evt, \
                      water_time * 10);
  }
  return 0;
}

signed char S_Auto_Plant_Handle_Water_Plant(unsigned char plant_num)
{
  
  if(s_auto_plant_para_running_with_adc_value == S_Auto_Plant_Para_Get_Running_Mode(&s_auto_plant_para)) {
    return s_auto_plant_handle_adc_mode(plant_num);
  } else {
    return s_auto_plant_handle_specail_water_time(plant_num);
  }

  // return 0;
}

void S_Auto_Plant_Handle_Water_Plant_Next(unsigned char plant_num)
{

//  unsigned char try = 0;
  s_auto_plant_para_running_mode run_mode = S_Auto_Plant_Para_Get_Running_Mode(&s_auto_plant_para);
  


  if(s_auto_plant_para_running_with_adc_value == run_mode) {
      if(s_auto_plant_datas.water_check_times_flag[plant_num] != 0U)
      {
        // Reduce check flag
        s_auto_plant_datas.water_check_times_flag[plant_num]--;
      }
  }

  
  // Stop motor first
  H_CC2640R2F_PWM_StopChannel_ByIndex(plant_num + 1);

  if(0U == s_auto_plant_datas.water_check_times_flag[0] && \
    0U == s_auto_plant_datas.water_check_times_flag[1] && s_auto_plant_para_running_with_adc_value == run_mode)
  {
    // next plan check
    printf("next plan check\r\n");
    S_Auto_Plant_Disable_Peripheral_Power();
    S_Auto_Plant_Set_Start_Plan();
  }
  else
  {
    if(0 == plant_num)
    {
      // need to check plant 1
      printf("ask check plant 1\r\n");
      S_AutoPlant_Ask_Start_WaterPlant(1);
    }
    else if(1 == plant_num)
    {
      printf("next check\r\n");
      S_Auto_Plant_Disable_Peripheral_Power();

      // for(try = 0; try < S_AUTO_PLANT_MAX_TIME_TRY_TIMES; try++)
      // {
      //   if(S_SD3077_Reset_RTC_Intr(S_Auto_Plant_Para_Get_Next_CheckSeconds(&s_auto_plant_para)))
      //   {
      //     Task_sleep(10000);
      //   }
      //   else
      //   {
      //     break;
      //   }
      // }
      S_LoopClock_Registe(loopclock_s_loopclock_handle_plant_check_evt, S_Auto_Plant_Para_Get_Next_CheckSeconds(&s_auto_plant_para) * 100);


      // S_SD3077_Reset_RTC_Intr(S_Auto_Plant_Para_Get_Next_CheckSeconds(&s_auto_plant_para));
    }
  }
}




